document.addEventListener('DOMContentLoaded', () => {
    const board = document.getElementById('board');
    const size = 19;

    let playerColor = 'black';
    let currentPlayer = 'black';
    let gameHistory = [];
    let boardStateHistory = []; // 保存每一步的完整棋盘状态
    let boardState = Array(size).fill(null).map(() => Array(size).fill(null));
    let gameMode = 'play'; // 'play' or 'replay'
    let playMode = 'free'; // 'free', 'vsAI-black', 'vsAI-white', 'aiVsAi'
    let aiLevel = 'medium'; // 'easy', 'medium', 'hard'
    let blackCaptured = 0; // 黑方提掉的白子数
    let whiteCaptured = 0; // 白方提掉的黑子数
    let aiGameRunning = false; // AI对战是否正在运行
    let aiGamePaused = false; // AI对战是否暂停
    let aiGameTimer = null; // AI对战定时器
    let consecutivePassCount = 0; // 连续pass次数（用于判断结束）
    let koPoint = null; // 劫争点：禁止立即回提的位置 {row, col}
    let showHeatmap = false; // 是否显示AI思考热图
    let showSuggestions = false; // 是否显示AI建议

    // --- UI Elements ---
    const freeModeBtn = document.getElementById('freeMode');
    const playAsBlackBtn = document.getElementById('playAsBlack');
    const playAsWhiteBtn = document.getElementById('playAsWhite');
    const aiVsAiBtn = document.getElementById('aiVsAi');
    const aiControlsDiv = document.querySelector('.ai-controls');
    const startAiGameBtn = document.getElementById('startAiGame');
    const pauseAiGameBtn = document.getElementById('pauseAiGame');
    const stopAiGameBtn = document.getElementById('stopAiGame');
    const aiStatusSpan = document.getElementById('ai-status');
    const aiEasyBtn = document.getElementById('aiEasy');
    const aiMediumBtn = document.getElementById('aiMedium');
    const aiHardBtn = document.getElementById('aiHard');
    const showHeatmapCheckbox = document.getElementById('showHeatmap');
    const showSuggestionsCheckbox = document.getElementById('showSuggestions');
    const undoBtn = document.getElementById('undoMove');
    const saveSgfBtn = document.getElementById('saveSgf');
    const loadSgfInput = document.getElementById('loadSgf');
    const replayControls = document.querySelector('.replay-controls');
    const moveCounter = document.getElementById('move-counter');
    const replayStartBtn = document.getElementById('replayStart');
    const replayPrevBtn = document.getElementById('replayPrev');
    const replayNextBtn = document.getElementById('replayNext');
    const replayEndBtn = document.getElementById('replayEnd');
    const commentBox = document.getElementById('comment-box');
    const commentText = document.getElementById('comment-text');
    const colLabels = document.getElementById('col-labels');
    const rowLabels = document.getElementById('row-labels');
    const blackTerritoryEl = document.getElementById('black-territory');
    const whiteTerritoryEl = document.getElementById('white-territory');
    const neutralTerritoryEl = document.getElementById('neutral-territory');
    const blackCapturedEl = document.getElementById('black-captured');
    const whiteCapturedEl = document.getElementById('white-captured');

    let previewStone = null;

    function initializeBoard() {
        board.innerHTML = '';
        boardState = Array(size).fill(null).map(() => Array(size).fill(null));
        gameHistory = [];
        boardStateHistory = [];
        currentPlayer = 'black';
        gameMode = 'play';
        replayControls.style.display = 'none';
        if (commentBox) commentBox.style.display = 'none';
        blackCaptured = 0;
        whiteCaptured = 0;
        consecutivePassCount = 0;
        koPoint = null;
        stopAiGame();
        updateCaptureDisplay();
        updateUndoButton();

        // Initialize coordinate labels
        if (colLabels && rowLabels) {
            colLabels.innerHTML = '';
            rowLabels.innerHTML = '';
            
            // Column labels (A-T, skip I)
            const colLetters = 'ABCDEFGHJKLMNOPQRST';
            for (let i = 0; i < size; i++) {
                const span = document.createElement('span');
                span.textContent = colLetters[i];
                span.style.left = (i * 30 + 15) + 'px'; // Position at center of each cell (15px)
                colLabels.appendChild(span);
            }
            
            // Row labels (19-1, top to bottom)
            for (let i = 0; i < size; i++) {
                const span = document.createElement('span');
                span.textContent = size - i;
                span.style.top = (i * 30 + 15) + 'px'; // Position at center of each cell (15px)
                rowLabels.appendChild(span);
            }
        }

        for (let i = 0; i < size * size; i++) {
            const intersection = document.createElement('div');
            intersection.classList.add('intersection');
            intersection.dataset.row = Math.floor(i / size);
            intersection.dataset.col = i % size;
            board.appendChild(intersection);
        }
        updatePlayerSelectionUI();
        updateTerritory();
    }

    function updatePlayerSelectionUI() {
        freeModeBtn.classList.toggle('selected', playMode === 'free');
        playAsBlackBtn.classList.toggle('selected', playMode === 'vsAI-black');
        playAsWhiteBtn.classList.toggle('selected', playMode === 'vsAI-white');
        aiVsAiBtn.classList.toggle('selected', playMode === 'aiVsAi');
        
        // 显示/隐藏 AI 控制按钮
        if (aiControlsDiv) {
            aiControlsDiv.style.display = playMode === 'aiVsAi' ? 'flex' : 'none';
        }
        
        aiEasyBtn.classList.toggle('selected', aiLevel === 'easy');
        aiMediumBtn.classList.toggle('selected', aiLevel === 'medium');
        aiHardBtn.classList.toggle('selected', aiLevel === 'hard');
        
        updateAIVisualization(); // Update visualization when mode changes
    }

    function placeStone(row, col, color) {
        if (row < 0 || row >= size || col < 0 || col >= size || boardState[row][col]) {
            return false;
        }

        // 检查是否违反劫争规则
        if (koPoint && koPoint.row === row && koPoint.col === col) {
            return false; // 禁止立即回提
        }

        // Find the top-left of the intersection cell
        const intersection = board.querySelector(`[data-row='${row}'][data-col='${col}']`);
        if (intersection) {
            const stone = document.createElement('div');
            stone.classList.add('stone', color);
            
            // The stone is positioned relative to the intersection div.
            // Since the stone's transform origin is its center, we place it at the top-left (0,0) 
            // of the intersection div, and the transform(-50%, -50%) will center it on the point.
            intersection.appendChild(stone);
            boardState[row][col] = color;
            
            // Check for captures after placing the stone
            const isValid = checkCaptures(row, col, color);
            
            return isValid;
        }
        return false;
    }

    // 检查并移除被提掉的棋子
    function checkCaptures(row, col, color) {
        const opponentColor = color === 'black' ? 'white' : 'black';
        const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
        
        let totalCaptured = 0;
        let capturedPositions = [];
        
        // 检查对手的相邻棋子组是否被提
        for (const [dr, dc] of directions) {
            const adjRow = row + dr;
            const adjCol = col + dc;
            if (adjRow >= 0 && adjRow < size && adjCol >= 0 && adjCol < size &&
                boardState[adjRow][adjCol] === opponentColor) {
                if (countLiberties(adjRow, adjCol, opponentColor) === 0) {
                    const captured = removeGroup(adjRow, adjCol, opponentColor, capturedPositions);
                    totalCaptured += captured;
                    if (color === 'black') {
                        blackCaptured += captured;
                    } else {
                        whiteCaptured += captured;
                    }
                }
            }
        }
        
        // 劫争规则：如果只提了一个子，且当前落子后自己只有一个子，记录劫争点
        if (totalCaptured === 1 && capturedPositions.length === 1) {
            // 检查当前落子位置的己方棋子组大小
            const myGroupSize = getGroupSize(row, col, color);
            if (myGroupSize === 1) {
                // 这是一个劫争，禁止对方立即回提
                koPoint = { row: capturedPositions[0].row, col: capturedPositions[0].col };
            } else {
                koPoint = null;
            }
        } else {
            // 不是劫争或提了多个子，清除劫争点
            koPoint = null;
        }
        
        // 检查自己是否自杀（围棋规则通常不允许自杀，除非能提掉对方）
        // 这里我们简单处理，如果自己没有气了就撤销这步棋
        if (countLiberties(row, col, color) === 0) {
            // 自杀手，撤销
            const intersection = board.querySelector(`[data-row='${row}'][data-col='${col}']`);
            if (intersection) {
                const stone = intersection.querySelector('.stone');
                if (stone) stone.remove();
            }
            boardState[row][col] = null;
            koPoint = null; // 撤销时清除劫争点
            return false;
        }
        
        updateCaptureDisplay();
        return true;
    }

    // 获取棋子组的大小
    function getGroupSize(row, col, color) {
        const visited = Array(size).fill(null).map(() => Array(size).fill(false));
        let count = 0;
        
        function dfs(r, c) {
            if (r < 0 || r >= size || c < 0 || c >= size || visited[r][c]) return;
            if (boardState[r][c] !== color) return;
            
            visited[r][c] = true;
            count++;
            
            const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
            for (const [dr, dc] of directions) {
                dfs(r + dr, c + dc);
            }
        }
        
        dfs(row, col);
        return count;
    }

    // 计算一个棋子组的气数
    function countLiberties(row, col, color) {
        const visited = Array(size).fill(null).map(() => Array(size).fill(false));
        const liberties = new Set();
        
        function dfs(r, c) {
            if (r < 0 || r >= size || c < 0 || c >= size || visited[r][c]) return;
            visited[r][c] = true;
            
            if (boardState[r][c] === null) {
                liberties.add(`${r},${c}`);
                return;
            }
            
            if (boardState[r][c] !== color) return;
            
            const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
            for (const [dr, dc] of directions) {
                dfs(r + dr, c + dc);
            }
        }
        
        dfs(row, col);
        return liberties.size;
    }

    // 移除一个被提的棋子组
    function removeGroup(row, col, color, capturedPositions = []) {
        const visited = Array(size).fill(null).map(() => Array(size).fill(false));
        let count = 0;
        
        function dfs(r, c) {
            if (r < 0 || r >= size || c < 0 || c >= size || visited[r][c]) return;
            if (boardState[r][c] !== color) return;
            
            visited[r][c] = true;
            count++;
            
            // 记录被提子的位置
            capturedPositions.push({ row: r, col: c });
            
            // 从DOM中移除棋子
            const intersection = board.querySelector(`[data-row='${r}'][data-col='${c}']`);
            if (intersection) {
                const stone = intersection.querySelector('.stone');
                if (stone) stone.remove();
            }
            boardState[r][c] = null;
            
            const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
            for (const [dr, dc] of directions) {
                dfs(r + dr, c + dc);
            }
        }
        
        dfs(row, col);
        return count;
    }

    // 更新提子数显示
    function updateCaptureDisplay() {
        if (blackCapturedEl) blackCapturedEl.textContent = blackCaptured;
        if (whiteCapturedEl) whiteCapturedEl.textContent = whiteCaptured;
    }

    // 保存当前棋盘状态
    function saveBoardState() {
        const state = {
            board: boardState.map(row => [...row]),
            blackCaptured: blackCaptured,
            whiteCaptured: whiteCaptured,
            currentPlayer: currentPlayer
        };
        boardStateHistory.push(state);
    }

    // 悔棋功能
    function undoMove() {
        if (gameMode !== 'play' || boardStateHistory.length === 0) {
            return;
        }

        // 对于对战模式，需要悔两步（玩家的一步和AI的一步）
        const stepsToUndo = (playMode === 'vsAI-black' || playMode === 'vsAI-white') ? 2 : 1;
        
        for (let i = 0; i < stepsToUndo; i++) {
            if (boardStateHistory.length === 0) break;
            
            // 移除最后一步
            gameHistory.pop();
            boardStateHistory.pop();
        }

        // 恢复到上一个状态
        if (boardStateHistory.length > 0) {
            const lastState = boardStateHistory[boardStateHistory.length - 1];
            boardState = lastState.board.map(row => [...row]);
            blackCaptured = lastState.blackCaptured;
            whiteCaptured = lastState.whiteCaptured;
            currentPlayer = lastState.currentPlayer;
        } else {
            // 如果没有历史状态，回到初始状态
            boardState = Array(size).fill(null).map(() => Array(size).fill(null));
            blackCaptured = 0;
            whiteCaptured = 0;
            currentPlayer = 'black';
        }

        // 重新绘制棋盘
        board.querySelectorAll('.stone').forEach(s => s.remove());
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col]) {
                    const intersection = board.querySelector(`[data-row='${row}'][data-col='${col}']`);
                    if (intersection) {
                        const stone = document.createElement('div');
                        stone.classList.add('stone', boardState[row][col]);
                        intersection.appendChild(stone);
                    }
                }
            }
        }

        koPoint = null; // 悔棋后清除劫争点
        updateCaptureDisplay();
        updateTerritory();
        updateUndoButton();
        updateAIVisualization(); // Update visualization after undo
    }

    // 更新悔棋按钮状态
    // 更新悔棋按钮状态
    function updateUndoButton() {
        if (undoBtn) {
            undoBtn.disabled = (gameMode !== 'play' || boardStateHistory.length === 0 || playMode === 'aiVsAi');
        }
    }

    function showPreview(row, col) {
        if (row < 0 || row >= size || col < 0 || col >= size || boardState[row][col]) {
            return;
        }
        
        hidePreview(); // Remove any existing preview

        const intersection = board.querySelector(`[data-row='${row}'][data-col='${col}']`);
        if (intersection) {
            previewStone = document.createElement('div');
            previewStone.classList.add('stone', currentPlayer, 'stone-preview');
            intersection.appendChild(previewStone);
        }
    }

    function hidePreview() {
        if (previewStone) {
            previewStone.remove();
            previewStone = null;
        }
    }

    // --- Territory Calculation ---
    function updateTerritory() {
        const visited = Array(size).fill(null).map(() => Array(size).fill(false));
        let blackTerritory = 0;
        let whiteTerritory = 0;
        let neutralTerritory = 0;

        // First, count stones on the board
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col] === 'black') {
                    blackTerritory++;
                } else if (boardState[row][col] === 'white') {
                    whiteTerritory++;
                }
            }
        }

        // Then, count empty territories
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (!visited[row][col] && boardState[row][col] === null) {
                    const result = floodFill(row, col, visited);
                    if (result.owner === 'black') {
                        blackTerritory += result.size;
                    } else if (result.owner === 'white') {
                        whiteTerritory += result.size;
                    } else {
                        // Neutral territory (touched by both colors or no color)
                        neutralTerritory += result.size;
                    }
                }
            }
        }

        if (blackTerritoryEl) blackTerritoryEl.textContent = blackTerritory;
        if (whiteTerritoryEl) whiteTerritoryEl.textContent = whiteTerritory;
        if (neutralTerritoryEl) neutralTerritoryEl.textContent = neutralTerritory;
    }

    function floodFill(startRow, startCol, visited) {
        const queue = [[startRow, startCol]];
        visited[startRow][startCol] = true;
        let emptyCount = 0;
        const adjacentColors = new Set();

        while (queue.length > 0) {
            const [row, col] = queue.shift();
            emptyCount++;

            // Check all 4 directions
            const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
            for (const [dr, dc] of directions) {
                const newRow = row + dr;
                const newCol = col + dc;

                if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size) {
                    if (boardState[newRow][newCol] === null && !visited[newRow][newCol]) {
                        visited[newRow][newCol] = true;
                        queue.push([newRow, newCol]);
                    } else if (boardState[newRow][newCol] !== null) {
                        adjacentColors.add(boardState[newRow][newCol]);
                    }
                }
            }
        }

        // Determine owner: if only one color borders this empty area, it belongs to that color
        let owner = null;
        if (adjacentColors.size === 1) {
            owner = Array.from(adjacentColors)[0];
        }

        return { size: emptyCount, owner };
    }

    function aiMove() {
        if (gameMode !== 'play') return false;
        
        let row, col;
        let placed = false;
        
        // Choose AI strategy based on level
        if (aiLevel === 'easy') {
            placed = aiMoveRandom();
        } else if (aiLevel === 'medium') {
            placed = aiMoveMedium();
        } else {
            placed = aiMoveHard();
        }
        
        if (placed) {
            consecutivePassCount = 0; // 成功落子，重置pass计数
            updateTerritory();
            updateUndoButton();
            updateAIVisualization(); // Update visualization after AI move
        } else {
            // 无法落子，记录为pass
            consecutivePassCount++;
        }
        
        return placed;
    }

    // AI对战模式控制
    function startAiGame() {
        if (playMode !== 'aiVsAi') return;
        
        aiGameRunning = true;
        aiGamePaused = false;
        updateAiGameUI();
        runAiGame();
    }

    function pauseAiGame() {
        if (!aiGameRunning) return;
        
        aiGamePaused = !aiGamePaused;
        updateAiGameUI();
        
        if (!aiGamePaused) {
            runAiGame(); // 继续游戏
        } else {
            if (aiGameTimer) {
                clearTimeout(aiGameTimer);
                aiGameTimer = null;
            }
        }
    }

    function stopAiGame() {
        aiGameRunning = false;
        aiGamePaused = false;
        if (aiGameTimer) {
            clearTimeout(aiGameTimer);
            aiGameTimer = null;
        }
        updateAiGameUI();
    }

    function runAiGame() {
        if (!aiGameRunning || aiGamePaused) return;
        
        // 检查是否游戏结束
        if (isGameOver()) {
            stopAiGame();
            updateAiGameUI('游戏结束');
            showGameResult();
            return;
        }
        
        // AI 落子
        const moved = aiMove();
        
        // 如果连续两次无法落子（双方都pass），游戏结束
        if (consecutivePassCount >= 2) {
            stopAiGame();
            updateAiGameUI('游戏结束');
            showGameResult();
            return;
        }
        
        // 继续下一步
        if (aiGameRunning && !aiGamePaused) {
            aiGameTimer = setTimeout(runAiGame, 1500); // 1500毫秒间隔
        }
    }

    function isGameOver() {
        // 检查棋盘是否几乎满了（超过90%）
        let filledCount = 0;
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col] !== null) {
                    filledCount++;
                }
            }
        }
        const fillRate = filledCount / (size * size);
        
        // 如果棋盘超过90%被占用，或者连续两次pass，游戏结束
        return fillRate > 0.9 || consecutivePassCount >= 2;
    }

    function showGameResult() {
        updateTerritory();
        const blackScore = parseInt(blackTerritoryEl.textContent) + blackCaptured * 1;
        const whiteScore = parseInt(whiteTerritoryEl.textContent) + whiteCaptured * 1;
        
        let result = '';
        if (blackScore > whiteScore) {
            result = `黑方获胜！ (黑: ${blackScore} vs 白: ${whiteScore})`;
        } else if (whiteScore > blackScore) {
            result = `白方获胜！ (白: ${whiteScore} vs 黑: ${blackScore})`;
        } else {
            result = `平局！ (黑: ${blackScore} vs 白: ${whiteScore})`;
        }
        
        alert(result);
    }

    function updateAiGameUI(status = null) {
        if (!aiStatusSpan) return;
        
        if (status) {
            aiStatusSpan.textContent = status;
        } else if (!aiGameRunning) {
            aiStatusSpan.textContent = '就绪';
        } else if (aiGamePaused) {
            aiStatusSpan.textContent = '已暂停';
        } else {
            aiStatusSpan.textContent = '运行中...';
        }
        
        if (startAiGameBtn) startAiGameBtn.disabled = aiGameRunning;
        if (pauseAiGameBtn) {
            pauseAiGameBtn.disabled = !aiGameRunning;
            pauseAiGameBtn.textContent = aiGamePaused ? '继续' : '暂停';
        }
        if (stopAiGameBtn) stopAiGameBtn.disabled = !aiGameRunning;
    }

    // 初级AI：随机下棋
    function aiMoveRandom() {
        const emptyPositions = [];
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col] === null) {
                    // 跳过劫争禁止点
                    if (koPoint && koPoint.row === row && koPoint.col === col) {
                        continue;
                    }
                    emptyPositions.push({ row, col });
                }
            }
        }
        
        if (emptyPositions.length === 0) return false;
        
        // 尝试所有空位置，直到找到合法的
        while (emptyPositions.length > 0) {
            const randomIndex = Math.floor(Math.random() * emptyPositions.length);
            const pos = emptyPositions[randomIndex];
            
            if (placeStone(pos.row, pos.col, currentPlayer)) {
                gameHistory.push({ row: pos.row, col: pos.col, color: currentPlayer });
                saveBoardState(); // 保存棋盘状态
                currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                return true;
            }
            
            // 如果这个位置不合法（自杀手），从列表中移除并重试
            emptyPositions.splice(randomIndex, 1);
        }
        
        return false;
    }

    // 中级AI：优先选择有价值的位置
    function aiMoveMedium() {
        const moves = [];
        
        // 1. 寻找可以占角的位置（4-4点，3-4点等）
        const corners = [
            [3, 3], [3, 15], [15, 3], [15, 15], // 4-4点（星位）
            [2, 3], [3, 2], [2, 15], [3, 16], [15, 2], [16, 3], [15, 16], [16, 15] // 3-4点
        ];
        
        for (const [r, c] of corners) {
            if (boardState[r][c] === null) {
                moves.push({ row: r, col: c, priority: 10 });
            }
        }
        
        // 2. 寻找对手棋子周围的位置（进攻/防守）
        const opponentColor = currentPlayer === 'black' ? 'white' : 'black';
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col] === opponentColor) {
                    // 检查周围的空位
                    const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
                    for (const [dr, dc] of directions) {
                        const newRow = row + dr;
                        const newCol = col + dc;
                        if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size && 
                            boardState[newRow][newCol] === null) {
                            // 跳过劫争禁止点
                            if (koPoint && koPoint.row === newRow && koPoint.col === newCol) {
                                continue;
                            }
                            moves.push({ row: newRow, col: newCol, priority: 5 });
                        }
                    }
                }
            }
        }
        
        // 3. 如果没有好的位置，随机选择空位
        if (moves.length === 0) {
            for (let row = 0; row < size; row++) {
                for (let col = 0; col < size; col++) {
                    if (boardState[row][col] === null) {
                        // 跳过劫争禁止点
                        if (koPoint && koPoint.row === row && koPoint.col === col) {
                            continue;
                        }
                        moves.push({ row, col, priority: 1 });
                    }
                }
            }
        }
        
        if (moves.length === 0) return false;
        
        // 按优先级排序并选择
        moves.sort((a, b) => b.priority - a.priority);
        const topMoves = moves.filter(m => m.priority === moves[0].priority);
        
        // 尝试多个高优先级位置，直到找到合法的
        for (const move of topMoves) {
            if (placeStone(move.row, move.col, currentPlayer)) {
                gameHistory.push({ row: move.row, col: move.col, color: currentPlayer });
                saveBoardState(); // 保存棋盘状态
                currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                return true;
            }
        }
        
        // 如果高优先级位置都不合法，尝试其他位置
        for (const move of moves) {
            if (placeStone(move.row, move.col, currentPlayer)) {
                gameHistory.push({ row: move.row, col: move.col, color: currentPlayer });
                saveBoardState(); // 保存棋盘状态
                currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                return true;
            }
        }
        
        return false;
    }

    // 高级AI：更复杂的策略
    function aiMoveHard() {
        const myColor = currentPlayer;
        const opponentColor = currentPlayer === 'black' ? 'white' : 'black';
        
        // 1. 优先检查定式（开局前10手）
        if (gameHistory.length < 10) {
            const josekiMove = checkJosekiMove(myColor);
            if (josekiMove) {
                // 验证定式位置是否合法
                if (placeStone(josekiMove.row, josekiMove.col, currentPlayer)) {
                    gameHistory.push({ row: josekiMove.row, col: josekiMove.col, color: currentPlayer });
                    saveBoardState();
                    currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                    return true;
                }
            }
        }
        
        // 2. 使用评估函数计算所有位置的价值
        const moves = [];
        
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col] === null) {
                    const score = evaluatePosition(row, col, myColor, opponentColor);
                    if (score > 0) {
                        moves.push({ row, col, priority: score });
                    }
                }
            }
        }
        
        if (moves.length === 0) {
            return aiMoveMedium(); // 回退到中级AI
        }
        
        // 按评分排序
        moves.sort((a, b) => b.priority - a.priority);
        const topMoves = moves.filter(m => m.priority >= moves[0].priority * 0.8);
        
        // 尝试高评分的位置，直到找到合法的
        for (const move of topMoves) {
            if (placeStone(move.row, move.col, currentPlayer)) {
                gameHistory.push({ row: move.row, col: move.col, color: currentPlayer });
                saveBoardState(); // 保存棋盘状态
                currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                return true;
            }
        }
        
        // 如果所有高评分位置都不合法，尝试其他位置
        for (const move of moves) {
            if (placeStone(move.row, move.col, currentPlayer)) {
                gameHistory.push({ row: move.row, col: move.col, color: currentPlayer });
                saveBoardState(); // 保存棋盘状态
                currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                return true;
            }
        }
        
        // 最后回退到中级AI
        return aiMoveMedium();
    }

    // 定式库：常见开局模式
    // 坐标系统：以棋盘左上角为原点 (0,0)，右下角为 (18,18)
    const josekiPatterns = {
        // 空棋盘的第一手：四个角的星位（3-3点）
        firstMoves: [
            { row: 3, col: 3 },    // 左上星位
            { row: 3, col: 15 },   // 右上星位
            { row: 15, col: 3 },   // 左下星位
            { row: 15, col: 15 }   // 右下星位
        ],
        
        // 小目定式（3-3点附近的常见应手）
        cornerResponses: {
            // 如果对手占了星位，推荐的应手位置
            starPoint: [
                { dr: -1, dc: 2 },  // 小飞挂角
                { dr: -1, dc: 1 },  // 一间高挂
                { dr: -2, dc: 1 },  // 大飞挂角
                { dr: 1, dc: 2 },   // 对称位置
                { dr: 1, dc: 1 },
                { dr: 2, dc: 1 }
            ],
            
            // 如果对手占了小目（3-4点），推荐的应手
            komoku: [
                { dr: 0, dc: 2 },   // 一间低挂
                { dr: 1, dc: 2 },   // 一间高挂
                { dr: -1, dc: 3 },  // 大飞挂角
                { dr: 1, dc: 3 }
            ]
        }
    };

    // 检查是否匹配定式
    function checkJosekiMove(color) {
        const moveCount = gameHistory.length;
        
        // 第一手：推荐四个角的星位
        if (moveCount === 0) {
            return josekiPatterns.firstMoves[Math.floor(Math.random() * 4)];
        }
        
        // 第二手：如果对手占了角，在另一个空角下
        if (moveCount === 1) {
            const firstMove = gameHistory[0];
            const occupiedCorners = new Set([`${firstMove.row},${firstMove.col}`]);
            const availableCorners = josekiPatterns.firstMoves.filter(
                corner => !occupiedCorners.has(`${corner.row},${corner.col}`)
            );
            if (availableCorners.length > 0) {
                return availableCorners[Math.floor(Math.random() * availableCorners.length)];
            }
        }
        
        // 前10手：尝试应用角部定式
        if (moveCount < 10) {
            const lastMove = gameHistory[gameHistory.length - 1];
            
            // 检查对手是否在角部（星位附近）
            for (const starPos of josekiPatterns.firstMoves) {
                if (lastMove.row === starPos.row && lastMove.col === starPos.col) {
                    // 对手占了星位，尝试挂角
                    const responses = josekiPatterns.cornerResponses.starPoint;
                    for (const resp of responses) {
                        const newRow = starPos.row + resp.dr;
                        const newCol = starPos.col + resp.dc;
                        if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size &&
                            boardState[newRow][newCol] === null) {
                            return { row: newRow, col: newCol };
                        }
                    }
                }
            }
            
            // 检查是否有空角可以占
            for (const corner of josekiPatterns.firstMoves) {
                if (boardState[corner.row][corner.col] === null) {
                    // 检查这个角是否有对手的子
                    let hasOpponent = false;
                    for (let dr = -2; dr <= 2; dr++) {
                        for (let dc = -2; dc <= 2; dc++) {
                            const r = corner.row + dr;
                            const c = corner.col + dc;
                            if (r >= 0 && r < size && c >= 0 && c < size) {
                                if (boardState[r][c] !== null && boardState[r][c] !== color) {
                                    hasOpponent = true;
                                    break;
                                }
                            }
                        }
                        if (hasOpponent) break;
                    }
                    
                    // 如果是空角，直接占
                    if (!hasOpponent) {
                        return corner;
                    }
                }
            }
        }
        
        return null; // 没有找到合适的定式
    }

    // 评估位置的价值
    function evaluatePosition(row, col, myColor, opponentColor) {
        let score = 0;
        
        // 0. 检查是否是劫争禁止点，如果是则直接返回0（不考虑此位置）
        if (koPoint && koPoint.row === row && koPoint.col === col) {
            return 0;
        }
        
        // 1. 位置价值：角、边、中腹
        // 星位（3-3点）最高优先级
        if ((row === 3 || row === 15) && (col === 3 || col === 15)) {
            score += 25;
        }
        // 其他常见定式点（3-4, 4-3等）
        else if (((row === 2 || row === 16) && (col === 3 || col === 15)) ||
                 ((row === 3 || row === 15) && (col === 2 || col === 16))) {
            score += 20;
        }
        // 边上的重要点
        else if ((row < 5 || row > 13) && (col < 5 || col > 13)) {
            score += 12;
        }
        // 中腹
        else if (row >= 7 && row <= 11 && col >= 7 && col <= 11) {
            score += 8;
        }
        
        // 2. 检查周围的棋子情况
        const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; // 只检查直接相邻
        const diagonals = [[-1, -1], [-1, 1], [1, -1], [1, 1]]; // 对角
        
        let myAdjacentStones = 0;
        let opponentAdjacentStones = 0;
        let myDiagonalStones = 0;
        let opponentDiagonalStones = 0;
        let emptyAdjacentCount = 0;
        
        // 检查直接相邻位置
        for (const [dr, dc] of directions) {
            const newRow = row + dr;
            const newCol = col + dc;
            if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size) {
                if (boardState[newRow][newCol] === myColor) {
                    myAdjacentStones++;
                } else if (boardState[newRow][newCol] === opponentColor) {
                    opponentAdjacentStones++;
                } else {
                    emptyAdjacentCount++;
                }
            }
        }
        
        // 检查对角位置
        for (const [dr, dc] of diagonals) {
            const newRow = row + dr;
            const newCol = col + dc;
            if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size) {
                if (boardState[newRow][newCol] === myColor) {
                    myDiagonalStones++;
                } else if (boardState[newRow][newCol] === opponentColor) {
                    opponentDiagonalStones++;
                }
            }
        }
        
        // 3. 根据周围情况调整分数
        // 避免过度集中：如果周围己方棋子太多，降低分数
        if (myAdjacentStones === 0 && myDiagonalStones === 0) {
            // 开拓新区域：适度加分
            score += 10;
        } else if (myAdjacentStones === 1) {
            // 连接己方棋子：加分（延伸）
            score += 15;
        } else if (myAdjacentStones === 2) {
            // 两个相邻己方棋子：需要判断是否形成好形
            score += 8;
        } else if (myAdjacentStones >= 3) {
            // 过度集中：大幅降低分数（避免填自己的眼）
            score -= 10;
        }
        
        // 4. 对手棋子的影响
        if (opponentAdjacentStones > 0) {
            // 靠近对手：进攻或防守
            score += opponentAdjacentStones * 6;
            
            // 如果对手周围有多个子，可能需要紧急防守
            if (opponentAdjacentStones >= 2) {
                score += 10;
            }
        }
        
        // 5. 气的数量（空间价值）
        // 周围空点越多，说明有更多发展空间
        score += emptyAdjacentCount * 2;
        
        // 6. 检查是否能形成眼位或破坏对手眼位
        if (myAdjacentStones >= 2 && emptyAdjacentCount >= 2) {
            // 可能形成良好的结构
            score += 5;
        }
        
        // 6.1 眼位识别：检查是否在己方围空内部（真眼 vs 假眼）
        const eyeScore = evaluateEyePosition(row, col, myColor);
        if (eyeScore < 0) {
            // 这是己方的真眼或潜在眼位，不应该填
            score += eyeScore; // 大幅降低分数
        } else if (eyeScore > 0) {
            // 这是破坏对手眼位的好位置
            score += eyeScore;
        }
        
        // 7. 厚薄判断：检查是否形成厚势
        const thicknessScore = evaluateThickness(row, col, myColor);
        score += thicknessScore;
        
        // 8. 避免在已经密集的区域继续下子
        // 检查更大范围内的棋子密度
        let nearbyStones = 0;
        for (let r = Math.max(0, row - 2); r <= Math.min(size - 1, row + 2); r++) {
            for (let c = Math.max(0, col - 2); c <= Math.min(size - 1, col + 2); c++) {
                if (boardState[r][c] !== null) {
                    nearbyStones++;
                }
            }
        }
        // 如果周围区域太密集，降低分数
        if (nearbyStones > 8) {
            score -= 15;
        } else if (nearbyStones > 5) {
            score -= 8;
        }
        
        return Math.max(0, score); // 确保分数不为负
    }

    // 评估眼位价值
    function evaluateEyePosition(row, col, color) {
        const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
        const diagonals = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
        
        let myStones = 0;
        let opponentStones = 0;
        let emptySpaces = 0;
        
        // 检查四周
        for (const [dr, dc] of directions) {
            const newRow = row + dr;
            const newCol = col + dc;
            if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size) {
                if (boardState[newRow][newCol] === color) {
                    myStones++;
                } else if (boardState[newRow][newCol] === null) {
                    emptySpaces++;
                } else {
                    opponentStones++;
                }
            } else {
                // 边界算作己方（围空的一部分）
                myStones++;
            }
        }
        
        // 如果四周都是己方或边界，这可能是己方的眼
        if (myStones >= 3 && opponentStones === 0) {
            // 检查对角，判断真眼还是假眼
            let diagonalOpponent = 0;
            let diagonalEmpty = 0;
            for (const [dr, dc] of diagonals) {
                const newRow = row + dr;
                const newCol = col + dc;
                if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size) {
                    if (boardState[newRow][newCol] !== color && boardState[newRow][newCol] !== null) {
                        diagonalOpponent++;
                    } else if (boardState[newRow][newCol] === null) {
                        diagonalEmpty++;
                    }
                }
            }
            
            // 如果对角有敌子或空点，可能是假眼，但仍然不应该填
            if (diagonalOpponent >= 2) {
                return -10; // 可能是假眼，但不应该填
            } else {
                return -20; // 真眼，绝对不要填
            }
        }
        
        const opponentColor = color === 'black' ? 'white' : 'black';
        // 检查是否是破坏对手眼位的位置
        if (opponentStones >= 3) {
            return 15; // 破坏对手的眼很重要
        }
        
        return 0;
    }

    // 评估厚薄
    function evaluateThickness(row, col, color) {
        let score = 0;
        const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
        
        // 检查是否有连接的己方棋子形成厚势
        let connectedGroups = 0;
        const visited = new Set();
        
        for (const [dr, dc] of directions) {
            const newRow = row + dr;
            const newCol = col + dc;
            const key = `${newRow},${newCol}`;
            
            if (newRow >= 0 && newRow < size && newCol >= 0 && newCol < size &&
                !visited.has(key) && boardState[newRow][newCol] === color) {
                
                // 计算这个组的大小和气
                const groupSize = getGroupSize(newRow, newCol, color);
                const liberties = countLiberties(newRow, newCol, color);
                
                if (groupSize >= 3 && liberties >= 3) {
                    score += 8; // 连接到厚实的棋块
                    connectedGroups++;
                } else if (liberties <= 2) {
                    score += 12; // 救援危险的棋块
                }
                
                visited.add(key);
            }
        }
        
        // 如果能连接多个组，形成厚势
        if (connectedGroups >= 2) {
            score += 10;
        }
        
        return score;
    }

    // AI Visualization Functions
    function clearAIVisualization() {
        // Remove all heatmap overlays
        document.querySelectorAll('.heatmap-overlay').forEach(el => el.remove());
        // Remove all suggestion markers
        document.querySelectorAll('.suggestion-marker').forEach(el => el.remove());
        document.querySelectorAll('.suggestion-number').forEach(el => el.remove());
    }

    function updateAIVisualization() {
        clearAIVisualization();
        
        if (!showHeatmap && !showSuggestions) return;
        if (gameMode !== 'play') return;
        
        // Determine AI color
        let aiColor;
        if (playMode === 'vsAI-black') {
            aiColor = 'white';
        } else if (playMode === 'vsAI-white') {
            aiColor = 'black';
        } else if (playMode === 'aiVsAi') {
            aiColor = currentPlayer; // Show for current player in AI vs AI
        } else {
            return; // No AI in free mode
        }
        
        const opponentColor = aiColor === 'black' ? 'white' : 'black';
        
        // Calculate scores for all empty positions
        const scores = [];
        for (let row = 0; row < size; row++) {
            for (let col = 0; col < size; col++) {
                if (boardState[row][col] === null) {
                    const score = evaluatePosition(row, col, aiColor, opponentColor);
                    if (score > 0) {
                        scores.push({ row, col, score });
                    }
                }
            }
        }
        
        if (scores.length === 0) return;
        
        // Sort by score descending
        scores.sort((a, b) => b.score - a.score);
        
        // Find min and max scores for normalization
        const maxScore = scores[0].score;
        const minScore = scores[scores.length - 1].score;
        const scoreRange = maxScore - minScore;
        
        // Show heatmap
        if (showHeatmap) {
            scores.forEach(({ row, col, score }) => {
                const intersection = board.children[row * size + col];
                const heatmapDiv = document.createElement('div');
                heatmapDiv.className = 'heatmap-overlay';
                
                // Normalize score to 0-1 range
                const normalizedScore = scoreRange > 0 ? (score - minScore) / scoreRange : 0;
                
                // Create color gradient from blue (low) to red (high)
                const hue = 240 - (normalizedScore * 240); // 240 (blue) to 0 (red)
                const saturation = 80;
                const lightness = 30 + (normalizedScore * 20); // 30-50%
                heatmapDiv.style.backgroundColor = `hsla(${hue}, ${saturation}%, ${lightness}%, 0.6)`;
                
                // Show score as text for top positions
                if (normalizedScore > 0.7) {
                    heatmapDiv.textContent = Math.round(score);
                }
                
                intersection.appendChild(heatmapDiv);
            });
        }
        
        // Show top 5 suggestions
        if (showSuggestions) {
            const topSuggestions = scores.slice(0, 5);
            topSuggestions.forEach(({ row, col, score }, index) => {
                const intersection = board.children[row * size + col];
                
                // Add marker
                const marker = document.createElement('div');
                marker.className = `suggestion-marker rank-${index + 1}`;
                intersection.appendChild(marker);
                
                // Add number
                const number = document.createElement('div');
                number.className = 'suggestion-number';
                number.textContent = index + 1;
                intersection.appendChild(number);
            });
        }
    }

    function handleBoardClick(e) {
        if (gameMode !== 'play') return;

        // In AI vs AI mode, don't allow manual placement
        if (playMode === 'aiVsAi') return;

        // In free mode, allow any player to move
        // In AI mode, only allow human player to move
        if (playMode === 'vsAI-black' && currentPlayer !== 'black') return;
        if (playMode === 'vsAI-white' && currentPlayer !== 'white') return;

        const intersection = e.target.closest('.intersection');
        if (intersection) {
            const row = parseInt(intersection.dataset.row);
            const col = parseInt(intersection.dataset.col);

            // FIX: Check the logical board state, not the DOM, to allow placing a stone over a preview.
            if (boardState[row][col] === null) {
                if (placeStone(row, col, currentPlayer)) {
                    hidePreview(); // Hide preview after placing stone
                    gameHistory.push({ row, col, color: currentPlayer });
                    saveBoardState(); // 保存棋盘状态用于悔棋
                    currentPlayer = (currentPlayer === 'black') ? 'white' : 'black';
                    updateTerritory();
                    updateUndoButton();
                    updateAIVisualization(); // Update visualization after player move

                    // Trigger AI move after a short delay in AI mode
                    if (playMode !== 'free' && 
                        ((playMode === 'vsAI-black' && currentPlayer === 'white') ||
                         (playMode === 'vsAI-white' && currentPlayer === 'black'))) {
                        setTimeout(aiMove, 500);
                    }
                }
            }
        }
    }
    
    // --- SGF and Replay Logic ---
    function saveSgf() {
        const sgfChars = 'abcdefghijklmnopqrst';
        let sgfContent = `(;GM[1]FF[4]CA[UTF-8]AP[GoTrainSimple]SZ[19]`;
        
        gameHistory.forEach(move => {
            const player = move.color === 'black' ? 'B' : 'W';
            const colChar = sgfChars[move.col];
            const rowChar = sgfChars[move.row];
            sgfContent += `;${player}[${colChar}${rowChar}]`;
        });

        sgfContent += ')';

        const blob = new Blob([sgfContent], { type: 'application/x-go-sgf' });
        const a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = `game-${new Date().toISOString().slice(0,10)}.sgf`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }

    function loadSgf(e) {
        const file = e.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = (event) => {
            const content = event.target.result;
            parseSgf(content);
        };
        reader.readAsText(file);
    }

    function parseSgf(sgf) {
        initializeBoard();
        gameMode = 'replay';
        
        const sgfChars = 'abcdefghijklmnopqrst';
        gameHistory = [];
        
        // Split SGF into nodes (each node starts with ;)
        const nodes = sgf.split(';').filter(n => n.trim());
        
        for (let node of nodes) {
            // Check if this is a move node (B[...] or W[...])
            const moveMatch = node.match(/([BW])\[([a-s]{2})\]/);
            if (moveMatch) {
                const color = moveMatch[1] === 'B' ? 'black' : 'white';
                const col = sgfChars.indexOf(moveMatch[2][0]);
                const row = sgfChars.indexOf(moveMatch[2][1]);
                
                // Extract comment if present
                let comment = '';
                const commentMatch = node.match(/C\[([\s\S]*?)\]/);
                if (commentMatch) {
                    comment = commentMatch[1].replace(/\\\]/g, ']').trim();
                }
                
                console.log('Parsed move:', { row, col, color, comment }); // Debug
                gameHistory.push({ row, col, color, comment });
            }
        }

        console.log('Total moves parsed:', gameHistory.length); // Debug
        if (gameHistory.length > 0) {
            setupReplay();
        }
    }

    let replayIndex = 0;
    function setupReplay() {
        replayControls.style.display = 'flex';
        commentBox.style.display = 'block';
        replayIndex = 0;
        drawReplayState();
    }

    function drawReplayState() {
        // Clear board visually
        board.querySelectorAll('.stone').forEach(s => s.remove());
        // Clear board state
        boardState = Array(size).fill(null).map(() => Array(size).fill(null));

        for (let i = 0; i < replayIndex; i++) {
            const move = gameHistory[i];
            placeStone(move.row, move.col, move.color);
        }
        moveCounter.textContent = `${replayIndex} / ${gameHistory.length}`;
        
        // Update territory during replay
        updateTerritory();
        
        // Update comment
        if (replayIndex > 0 && gameHistory[replayIndex - 1]) {
            const currentMove = gameHistory[replayIndex - 1];
            commentText.textContent = currentMove.comment || '(无评论)';
        } else {
            commentText.textContent = '棋局开始';
        }
    }

    // --- Event Listeners ---
    board.addEventListener('click', handleBoardClick);

    board.addEventListener('mousemove', (e) => {
        if (gameMode !== 'play' || playMode === 'aiVsAi') return;
        
        // Show preview only if it's the appropriate turn
        if (playMode === 'vsAI-black' && currentPlayer !== 'black') return;
        if (playMode === 'vsAI-white' && currentPlayer !== 'white') return;
        
        const intersection = e.target.closest('.intersection');
        if (intersection) {
            const row = parseInt(intersection.dataset.row);
            const col = parseInt(intersection.dataset.col);
            if (!boardState[row][col]) {
                showPreview(row, col);
            } else {
                hidePreview();
            }
        }
    });

    board.addEventListener('mouseleave', () => {
        hidePreview();
    });

    freeModeBtn.addEventListener('click', () => {
        playMode = 'free';
        playerColor = 'black';
        initializeBoard();
    });

    playAsBlackBtn.addEventListener('click', () => {
        playMode = 'vsAI-black';
        playerColor = 'black';
        initializeBoard();
    });

    playAsWhiteBtn.addEventListener('click', () => {
        playMode = 'vsAI-white';
        playerColor = 'white';
        initializeBoard();
        currentPlayer = 'black';
        setTimeout(aiMove, 500); // AI plays first as black
    });

    aiVsAiBtn.addEventListener('click', () => {
        playMode = 'aiVsAi';
        initializeBoard();
        updatePlayerSelectionUI();
    });

    startAiGameBtn.addEventListener('click', startAiGame);
    pauseAiGameBtn.addEventListener('click', pauseAiGame);
    stopAiGameBtn.addEventListener('click', stopAiGame);

    saveSgfBtn.addEventListener('click', saveSgf);
    loadSgfInput.addEventListener('change', loadSgf);
    undoBtn.addEventListener('click', undoMove);

    aiEasyBtn.addEventListener('click', () => {
        aiLevel = 'easy';
        updatePlayerSelectionUI();
    });

    aiMediumBtn.addEventListener('click', () => {
        aiLevel = 'medium';
        updatePlayerSelectionUI();
    });

    aiHardBtn.addEventListener('click', () => {
        aiLevel = 'hard';
        updatePlayerSelectionUI();
    });

    showHeatmapCheckbox.addEventListener('change', (e) => {
        showHeatmap = e.target.checked;
        if (showHeatmap) {
            updateAIVisualization();
        } else {
            clearAIVisualization();
        }
    });

    showSuggestionsCheckbox.addEventListener('change', (e) => {
        showSuggestions = e.target.checked;
        if (showSuggestions) {
            updateAIVisualization();
        } else {
            clearAIVisualization();
        }
    });

    replayStartBtn.addEventListener('click', () => { replayIndex = 0; drawReplayState(); });
    replayPrevBtn.addEventListener('click', () => { if (replayIndex > 0) replayIndex--; drawReplayState(); });
    replayNextBtn.addEventListener('click', () => { if (replayIndex < gameHistory.length) replayIndex++; drawReplayState(); });
    replayEndBtn.addEventListener('click', () => { replayIndex = gameHistory.length; drawReplayState(); });

    // --- Initial Setup ---
    initializeBoard();
});
